/*
 * 
 * 
 * 
 */
package com.hboxs.asl.entity;

import com.hboxs.asl.Setting;
import com.hboxs.asl.util.SettingUtils;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.Predicate;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.time.DateUtils;

import javax.persistence.*;
import java.math.BigDecimal;
import java.util.*;

/**
 * Entity - 购物车
 */
@Entity
@Table(name = "xx_cart")
@SequenceGenerator(name = "sequenceGenerator", sequenceName = "xx_cart_sequence")
public class Cart extends BaseEntity {

    private static final long serialVersionUID = -6565967051825794561L;

    /**
     * 超时时间
     */
    public static final int TIMEOUT = 604800;

    /**
     * 最大商品数
     */
    public static final Integer MAX_PRODUCT_COUNT = 100;

    /**
     * "ID"Cookie名称
     */
    public static final String ID_COOKIE_NAME = "cartId";

    /**
     * "密钥"Cookie名称
     */
    public static final String KEY_COOKIE_NAME = "cartKey";

    /**
     * 密钥
     */
    private String key;

    /**
     * 会员
     */
    private Member member;

    /**
     * 购物车项
     */
    private Set<CartItem> cartItems = new HashSet<CartItem>();

    /**
     * 促销
     */
    private List<Promotion> promotions = new ArrayList<>();

    @ManyToMany(fetch = FetchType.LAZY)
    public List<Promotion> getPromotions() {
        return promotions;
    }

    public void setPromotions(List<Promotion> promotions) {
        this.promotions = promotions;
    }

    /**
     * 获取密钥
     *
     * @return 密钥
     */
    @Column(name = "cart_key", nullable = false, updatable = false)
    public String getKey() {
        return key;
    }

    /**
     * 设置密钥
     *
     * @param key 密钥
     */
    public void setKey(String key) {
        this.key = key;
    }

    /**
     * 获取会员
     *
     * @return 会员
     */
    @JoinColumn(name = "member",unique = true)
    @OneToOne(fetch = FetchType.LAZY)
    public Member getMember() {
        return member;
    }

    /**
     * 设置会员
     *
     * @param member 会员
     */
    public void setMember(Member member) {
        this.member = member;
    }

    /**
     * 获取购物车项
     *
     * @return 购物车项
     */
    @OneToMany(mappedBy = "cart", fetch = FetchType.LAZY, cascade = CascadeType.REMOVE)
    public Set<CartItem> getCartItems() {
        return cartItems;
    }

    /**
     * 设置购物车项
     *
     * @param cartItems 购物车项
     */
    public void setCartItems(Set<CartItem> cartItems) {
        this.cartItems = cartItems;
    }

    /**
     * 获取admin商品重量
     *
     * @return 商品重量
     */
    @Transient
    public int getWeight() {
        int weight = 0;
        if (getCartItems() != null) {
            for (CartItem cartItem : getCartItems()) {
                if (cartItem != null && cartItem.getIsSelected() && cartItem.getProduct().getMerchant()==null) {
                    weight += cartItem.getWeight();
                }
            }
        }
        return weight;
    }


    /**
     * 获取商品重量
     *
     * @return 商品重量
     */
    @Transient
    public int getWeight(Merchant merchant) {
        int weight = 0;
        if (getCartItems() != null) {
            for (CartItem cartItem : getCartItems()) {
                if (cartItem != null && cartItem.getIsSelected() && cartItem.getProduct().getMerchant()!=null && cartItem.getProduct().getMerchant()==merchant) {
                    weight += cartItem.getWeight();
                }
            }
        }
        return weight;
    }

    /**
     * 获取商品数量
     *
     * @return 商品数量
     */
    @Transient
    public int getQuantity() {
        int quantity = 0;
        if (getCartItems() != null) {
            for (CartItem cartItem : getCartItems()) {
                if (cartItem != null && cartItem.getQuantity() != null) {
                    quantity += cartItem.getQuantity();
                }
            }
        }
        return quantity;
    }

    /**
     * 获取赠送admin积分
     *
     * @return 赠送积分
     */
    @Transient
    public BigDecimal getPoint() {
        BigDecimal point = new BigDecimal(0);
        if (getCartItems() != null) {
            for (CartItem cartItem : getCartItems()) {
                if (cartItem != null && cartItem.getIsSelected() && cartItem.getProduct().getMerchant()==null ) {
                    point = point.add(cartItem.getPoint());
                }
            }
        }
        return point;
    }

    /**
     * 获取商家赠送的积分
     *
     * @return 赠送积分
     */
    @Transient
    public BigDecimal getPoint(Merchant merchant) {
        BigDecimal point = new BigDecimal(0);
        if (getCartItems() != null) {
            for (CartItem cartItem : getCartItems()) {
                if (cartItem != null && cartItem.getIsSelected() && cartItem.getProduct().getMerchant()!=null && cartItem.getProduct().getMerchant()==merchant) {
                    point = point.add(cartItem.getPoint());
                }
            }
        }
        return point;
    }

    /**
     * 获取商家赠送的积分，赠送给会员的
     *
     * @return 赠送积分
     */
    @Transient
    public BigDecimal getmPoint(Merchant merchant) {


        BigDecimal point = new BigDecimal(0);
        if (getCartItems() != null) {
            for (CartItem cartItem : getCartItems()) {
                if (cartItem != null && cartItem.getIsSelected() && cartItem.getProduct().getMerchant()!=null && cartItem.getProduct().getMerchant()==merchant) {
                    point = point.add(cartItem.getmPoint());
                }
            }
        }
        return point;
    }


    /**
     * 获取赠送积分增加值
     *
     * @return 赠送积分增加值
     */
    @Transient
    public BigDecimal getAddedPoint() {
        BigDecimal originalPoint = new BigDecimal(0);
        BigDecimal currentPoint = new BigDecimal(0);
        if (getCartItems() != null) {
            for (CartItem cartItem : getCartItems()) {
                if (cartItem != null) {
                    cartItem.setTempPoint(null);
                }
            }
        }
        BigDecimal addedPoint = currentPoint.subtract(originalPoint);
        return addedPoint.compareTo(new BigDecimal(0)) == 1 ? addedPoint : new BigDecimal(0);
    }

    /**
     * 获取商家赠送积分增加值
     *
     * @return 赠送积分增加值
     *
     * dinfeng : 此方法暂时不用
     */
    @Transient
    public BigDecimal getAddedPoint(Merchant merchant) {
        BigDecimal originalPoint = new BigDecimal(0);
        BigDecimal currentPoint = new BigDecimal(0);
        if (getCartItems() != null) {
            for (CartItem cartItem : getCartItems()) {
                if (cartItem != null && cartItem.getProduct().getMerchant()!=null && cartItem.getProduct().getMerchant()==merchant) {
                    cartItem.setTempPoint(null);
                }
            }
        }
        BigDecimal addedPoint = currentPoint.subtract(originalPoint);
        return addedPoint.compareTo(new BigDecimal(0)) == 1 ? addedPoint : new BigDecimal(0);
    }

    /**
     * 获取有效赠送积分
     *
     * @return 有效赠送积分
     */
    @Transient
    public BigDecimal getEffectivePoint() {
        BigDecimal effectivePoint = getPoint().add(getAddedPoint());
        return effectivePoint.compareTo(new BigDecimal(0)) == 1 ? effectivePoint : new BigDecimal(0);
    }

    /**
     * 获取商家赠送的积分
     *
     * @return 有效赠送积分
     */
    @Transient
    public BigDecimal getEffectivePoint(Merchant merchant) {
        BigDecimal effectivePoint = getPoint(merchant).add(getAddedPoint(merchant));
        return effectivePoint.compareTo(new BigDecimal(0)) == 1 ? effectivePoint : new BigDecimal(0);
    }

    /**
     * 获取商家赠送的积分，赠送给会员的
     *
     * @return 有效赠送积分
     */
    @Transient
    public BigDecimal getEffectivemPoint(Merchant merchant) {
        BigDecimal effectivemPoint = getmPoint(merchant).add(getAddedPoint(merchant));
        return effectivemPoint.compareTo(new BigDecimal(0)) == 1 ? effectivemPoint : new BigDecimal(0);
    }

    /**
     * 获取商品价格
     *
     * @return 商品价格
     */
    @Transient
    public BigDecimal getPrice() {
        BigDecimal price = new BigDecimal(0);
        if (getCartItems() != null) {
            for (CartItem cartItem : getCartItems()) {
                if (cartItem != null && cartItem.getSubtotal() != null && cartItem.getIsSelected()) {
                    price = price.add(cartItem.getSubtotal());
                }
            }
        }
        return price;
    }

    /**
     * 获取商家商品价格
     *
     * @return 商品价格
     */
    @Transient
    public BigDecimal getPrice(Merchant merchant) {
        BigDecimal price = new BigDecimal(0);
        if (getCartItems() != null) {
            for (CartItem cartItem : getCartItems()) {
                if (cartItem != null && cartItem.getSubtotal() != null && cartItem.getIsSelected() && cartItem.getProduct().getMerchant() == merchant) {
                    price = price.add(cartItem.getSubtotal());
                }
            }
        }
        return price;
    }


    /**
     * 获取折扣
     *
     * @return 折扣
     */
    @Transient
    public BigDecimal getDiscount() {
        BigDecimal originalPrice = new BigDecimal(0);
        BigDecimal currentPrice = new BigDecimal(0);
        if (getCartItems() != null) {
            for (CartItem cartItem : getCartItems()) {
                if (cartItem != null) {
                    cartItem.setTempPrice(null);
                }
            }
        }
        Setting setting = SettingUtils.get();
        BigDecimal discount = setting.setScale(originalPrice.subtract(currentPrice));
        return discount.compareTo(new BigDecimal(0)) > 0 ? discount : new BigDecimal(0);
    }

    /**
     * 获取有效商品价格
     *
     * @return 有效商品价格
     */
    @Transient
    public BigDecimal getEffectivePrice() {
        BigDecimal effectivePrice = getPrice().subtract(getDiscount());
        return effectivePrice.compareTo(new BigDecimal(0)) > 0 ? effectivePrice : new BigDecimal(0);
    }


    /**
     * 获取促销购物车项
     *
     * @param promotion 促销
     * @return 促销购物车项
     */
    @Transient
    public Set<CartItem> getCartItems(Promotion promotion) {
        Set<CartItem> cartItems = new HashSet<CartItem>();
        if (promotion != null && getCartItems() != null) {
            for (CartItem cartItem : getCartItems()) {
                if (cartItem != null && cartItem.getIsSelected() && cartItem.getProduct() != null && cartItem.getProduct().isValid(promotion)) {
                    cartItems.add(cartItem);
                }
            }
        }
        return cartItems;
    }

    /**
     * 获取促销商品数量
     *
     * @param promotion 促销
     * @return 促销商品数量
     */
    @Transient
    private int getQuantity(Promotion promotion) {
        int quantity = 0;
        for (CartItem cartItem : getCartItems(promotion)) {
            if (cartItem != null && cartItem.getQuantity() != null) {
                quantity += cartItem.getQuantity();
            }
        }
        return quantity;
    }

    /**
     * 获取促销商品赠送积分
     *
     * @param promotion 促销
     * @return 促销商品赠送积分
     */
    @Transient
    private BigDecimal getPoint(Promotion promotion) {
        BigDecimal point = new BigDecimal(0);
        for (CartItem cartItem : getCartItems(promotion)) {
            if (cartItem != null) {
                point = point.add(cartItem.getPoint());
            }
        }
        return point;
    }

    /**
     * 获取促销商品临时赠送积分
     *
     * @param promotion 促销
     * @return 促销商品临时赠送积分
     */
    @Transient
    private BigDecimal getTempPoint(Promotion promotion) {
        BigDecimal tempPoint = new BigDecimal(0);
        for (CartItem cartItem : getCartItems(promotion)) {
            if (cartItem != null && cartItem.getTempPoint() != null) {
                tempPoint = tempPoint.add(cartItem.getTempPoint());
            }
        }
        return tempPoint;
    }

    /**
     * 获取促销商品价格
     *
     * @param promotion 促销
     * @return 促销商品价格
     */
    @Transient
    private BigDecimal getPrice(Promotion promotion) {
        BigDecimal price = new BigDecimal(0);
        for (CartItem cartItem : getCartItems(promotion)) {
            if (cartItem != null && cartItem.getSubtotal() != null && cartItem.getIsSelected()) {
                price = price.add(cartItem.getSubtotal());
            }
        }
        return price;
    }

    /**
     * 获取促销商品临时价格
     *
     * @param promotion 促销
     * @return 促销商品临时价格
     */
    @Transient
    private BigDecimal getTempPrice(Promotion promotion) {
        BigDecimal tempPrice = new BigDecimal(0);
        for (CartItem cartItem : getCartItems(promotion)) {
            if (cartItem != null && cartItem.getTempPrice() != null) {
                tempPrice = tempPrice.add(cartItem.getTempPrice());
            }
        }
        return tempPrice;
    }

    /**
     * 判断促销是否有效
     *
     * @param promotion 促销
     * @return 促销是否有效
     */
    @Transient
    public boolean isValid(Promotion promotion) {
        if (promotion == null || !promotion.hasBegun() || promotion.hasEnded()) {
            return false;
        }
        /*if (promotion.getMemberRanks() == null || promotion.getMemberRanks().isEmpty() || getMember() == null || getMember().getMemberRank() == null || !promotion.getMemberRanks().contains(getMember().getMemberRank())) {
            return false;
        }*/
        /*Integer quantity = getQuantity(promotion);
        if ((promotion.getMinimumQuantity() != null && promotion.getMinimumQuantity() > quantity) || (promotion.getMaximumQuantity() != null && promotion.getMaximumQuantity() < quantity)) {
            return false;
        }*/
        BigDecimal price = getPrice(promotion);
        return !((promotion.getMinimumPrice() != null && promotion.getMinimumPrice().compareTo(price) > 0) || (promotion.getMaximumPrice() != null && promotion.getMaximumPrice().compareTo(price) < 0));
    }

    /**
     * 判断优惠券是否有效
     *
     * @param coupon 优惠券
     * @return 优惠券是否有效
     */
    @Transient
    public boolean isValid(Coupon coupon) {
        if (coupon == null || /*!coupon.getIsEnabled() ||*/ !coupon.hasBegun() || coupon.hasExpired()) {
            return false;
        }
        /*if ((coupon.getMinimumQuantity() != null && coupon.getMinimumQuantity() > getQuantity()) || (coupon.getMaximumQuantity() != null && coupon.getMaximumQuantity() < getQuantity())) {
            return false;
        }*/
//        return !((coupon.getMinimumPrice() != null && coupon.getMinimumPrice().compareTo(getEffectivePrice()) > 0) || (coupon.getMaximumPrice() != null && coupon.getMaximumPrice().compareTo(getEffectivePrice()) < 0));
        return coupon.getMaximumPrice() != null && coupon.getMaximumPrice().compareTo(getPrice()) <= 0;
    }

    /**
     * 获取购物车项
     *
     * @param product 商品
     * @return 购物车项
     */
    @Transient
    public CartItem getCartItem(Product product) {
        if (product != null && getCartItems() != null) {
            for (CartItem cartItem : getCartItems()) {
                if (cartItem != null && cartItem.getProduct() != null && cartItem.getProduct().equals(product)) {
                    return cartItem;
                }
            }
        }
        return null;
    }

    /**
     * 判断是否包含商品
     *
     * @param product 商品
     * @return 是否包含商品
     */
    @Transient
    public boolean contains(Product product) {
        if (product != null && getCartItems() != null) {
            for (CartItem cartItem : getCartItems()) {
                if (cartItem != null && cartItem.getProduct() != null && cartItem.getProduct().equals(product)) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 获取令牌
     *
     * @return 令牌
     */
    @Transient
    public String getToken() {
        HashCodeBuilder hashCodeBuilder = new HashCodeBuilder(17, 37).append(getKey());
        if (getCartItems() != null) {
            for (CartItem cartItem : getCartItems()) {
                hashCodeBuilder.append(cartItem.getProduct()).append(cartItem.getQuantity()).append(cartItem.getPrice());
            }
        }
        return DigestUtils.md5Hex(hashCodeBuilder.toString());
    }

    /**
     * 获取是否库存不足
     *
     * @return 是否库存不足
     */
    @Transient
    public boolean getIsLowStock() {
        if (getCartItems() != null) {
            for (CartItem cartItem : getCartItems()) {
                if (cartItem != null && cartItem.getIsLowStock()) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 判断是否已过期
     *
     * @return 是否已过期
     */
    @Transient
    public boolean hasExpired() {
        return new Date().after(DateUtils.addSeconds(getModifyDate(), TIMEOUT));
    }

    /**
     * 判断是否为空
     *
     * @return 是否为空
     */
    @Transient
    public boolean isEmpty() {
        return getCartItems() == null || getCartItems().isEmpty();
    }


    /**
     * 获取已选的购物项数量
     *
     * @return size 已选的购物项数量
     */
    @Transient
    public int getSelectedCartItemsSize() {
        int size = 0;
        for (CartItem ci : this.getCartItems()) {
            if (ci.getIsSelected()) {
                size++;
            }
        }
        return size;
    }


    /**
     * 获取不参与促销的购物车项
     */
    @Transient
    public Set<CartItem> getCartItemsWithoutPromotion() {
        Set<CartItem> cis = this.getCartItems();
        Set<CartItem> results = new HashSet<>();
        for (CartItem ci : cis) {
            if (ci.getIsSelected()) {
                Product p = ci.getProduct();
                if (
                        (p.getValidPromotions() != null && p.getValidPromotions().size() > 0)
                                ||
                                (p.getProductCategory() != null && p.getProductCategory().getValidPromotions() != null && p.getProductCategory().getValidPromotions().size() > 0)
                        ) {
                } else {
                    results.add(ci);
                }
            }
        }
        return results;
    }

    /**
     * 获取参与促销的购物车项
     */
    @Transient
    public Set<CartItem> getCartItemsWithPromotion() {
        Set<CartItem> cis = this.getCartItems();
        Set<CartItem> results = new HashSet<>();
        for (CartItem ci : cis) {
            if (ci.getIsSelected()) {
                Product p = ci.getProduct();
                if (
                        (p.getValidPromotions() != null && p.getPromotions().size() > 0)
                                ||
                                (p.getProductCategory() != null && p.getProductCategory().getValidPromotions() != null && p.getProductCategory().getValidPromotions().size() > 0)
                        ) {
                    results.add(ci);
                } else {

                }
            }
        }
        return results;
    }


    /**
     * 获取不参与促销的购物车项
     */
    @Transient
    public Set<CartItem> getCartItemsWithoutPromotion(Promotion promotion) {
        Set<CartItem> cis = this.getCartItems();
        Set<CartItem> results = new HashSet<>();
        for (CartItem ci : cis) {
            if (ci.getIsSelected()) {
                Product p = ci.getProduct();
                if (
                        (p.getValidPromotions() != null && p.getValidPromotions().size() > 0 && p.getValidPromotions().contains(promotion))
                                ||
                                (p.getProductCategory() != null && p.getProductCategory().getValidPromotions() != null && p.getProductCategory().getValidPromotions().size() > 0 && p.getProductCategory().getValidPromotions().contains(promotion))
                        ) {
                } else {
                    results.add(ci);
                }
            }
        }
        return results;
    }

    /**
     * 获取参与促销的购物车项
     */
    @Transient
    public Set<CartItem> getCartItemsWithPromotion(Promotion promotion) {
        Set<CartItem> cis = this.getCartItems();
        Set<CartItem> results = new HashSet<>();
        for (CartItem ci : cis) {
            if (ci.getIsSelected()) {
                Product p = ci.getProduct();
                if (
                        (p.getValidPromotions() != null && p.getValidPromotions().size() > 0 && p.getValidPromotions().contains(promotion))
                                ||
                                (p.getValidPromotions() != null && p.getProductCategory().getValidPromotions() != null && p.getProductCategory().getValidPromotions().size() > 0 && p.getProductCategory().getValidPromotions().contains(promotion))
                        ) {
                    results.add(ci);
                } else {

                }
            }
        }
        return results;
    }


    /**
     * 获取不参加促销部分的小计
     *
     * @return 小计
     */
    @Transient
    public BigDecimal getSubtotalWithoutPromotion() {
        BigDecimal price = new BigDecimal(0);
        //1.获取购物车项集合并且移除使用了促销的购物车项
        Set<CartItem> cis = getCartItems();
        //2.计算非促销购物车项的价格
        for (CartItem c : this.getCartItemsWithoutPromotion()) {
            if (c != null && c.getSubtotal() != null && c.getIsSelected()) {
                price = price.add(c.getSubtotal());
            }
        }
        return price;
    }

    /**
     * 获取不参加促销部分的小计
     *
     * @return 小计
     */
    @Transient
    public BigDecimal getSubtotalWithoutPromotion(Promotion promotion) {
        BigDecimal price = new BigDecimal(0);
        //1.获取购物车项集合并且移除使用了促销的购物车项
        Set<CartItem> cis = getCartItems();
        //2.计算非促销购物车项的价格
        for (CartItem c : this.getCartItemsWithoutPromotion(promotion)) {
            if (c != null && c.getSubtotal() != null && c.getIsSelected()) {
                price = price.add(c.getSubtotal());
            }
        }
        return price;
    }

    /**
     * 获取参加促销部分的小计
     *
     * @return 小计
     */
    @Transient
    public BigDecimal getSubtotalWithPromotion(Promotion promotion) {
        BigDecimal price = new BigDecimal(0);
        //1.获取购物车项集合并且移除使用了促销的购物车项
        Set<CartItem> cis = getCartItems();
        //2.计算促销购物车项的价格
        for (CartItem c : this.getCartItemsWithPromotion(promotion)) {
            if (c != null && c.getSubtotal() != null && c.getIsSelected()) {
                price = price.add(c.getSubtotal());
            }
        }
        return price;
    }

    /**
     * 获得店铺
     *
     * @return 店铺
     */
    @Transient
    public List<Merchant> getMerchants() {
        Set<Merchant> merchants = new HashSet<>();
        if (getCartItems() != null) {
            for (CartItem cartItem : getCartItems()) {
                if (cartItem != null && cartItem.getProduct().getMerchant() != null) {
                    merchants.add(cartItem.getProduct().getMerchant());
                }
            }
            return new ArrayList<Merchant>(merchants);
        }
        return Collections.emptyList();
    }


    /**
     * 是否存在自营店
     *
     * @return
     */
    @Transient
    public Boolean ifExistAdmin() {
        if (getCartItems() != null) {
            for (CartItem cartItem : getCartItems()) {
                if (cartItem != null && cartItem.getIsSelected() && cartItem.getProduct().getMerchant() == null) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 获取购物车项，购物车项是选择的
     *
     * @param merchant 店铺
     * @return 购物车项
     */
    @Transient
    public Set<CartItem> getCartItems(final Merchant merchant) {
        if (merchant == null) {
            return this.getCartItems();
        }
        Set<CartItem> cartItems = new HashSet<CartItem>();
        if (getCartItems() != null) {
            CollectionUtils.select(getCartItems(), new Predicate() {
                public boolean evaluate(Object object) {
                    CartItem cartItem = (CartItem) object;
                    if (cartItem == null) {
                        return false;
                    } else {
                        return (merchant.equals(cartItem.getProduct().getMerchant())&&cartItem.getIsSelected());
                    }
                }
            }, cartItems);
        }
        return cartItems;
    }

}